#include "../include/mine_map.h"
#include "../include/opt.h"
#include "../include/map.h"
#include <stdbool.h>
#include <stdio.h>
#include <time.h>
#define OPT_DEBUG 0
int opt(map *m, opt_t opt)
{
	/**
	 * @brief 操作类型
	 *
	 */
	int optMode;
	/**
	 * @brief 操作坐标
	 *
	 */
	int optX, optY;
	optX = opt.x;
	optY = opt.y;
	optMode = opt.mode;
	if (optX < 1 || optX > m->mx || optY < 1 || optY > m->my)
		return UNALLOWED;
	switch (optMode)
	{
	case OPT_LEFT_CLICK:
		return fnOptLeftClick(optX, optY, m);
		break;
	case OPT_MID_CLICK:
		return fnOptMidClick(optX, optY, m);
		break;
	case OPT_RIGTH_CLICK:
		return fnOptRightClick(optX, optY, m);
		break;
	case OPT_TOTAL_CLICK:
		return fnTotalFlag(m);
		break;
	default:
		return UNALLOWED;
		break;
	}
}

int opt_count(map *map, int x, int y)
{
	int cnt = 0;
	for (int i = x - 1; i <= x + 1; i++)
	{
		for (int j = y - 1; j <= y + 1; j++)
		{
			if (i < 1 || j < 1 || i > map->mx || j > map->my)
				continue;
			if (i == x && j == y)
				continue;
			if (map->mineMap[i][j] == 1)
				cnt++;
		}
	}
	return cnt;
}

int opt_flag_count(map *map, int x, int y)
{
	int cnt = 0;
	for (int i = x - 1; i <= x + 1; i++)
	{
		for (int j = y - 1; j <= y + 1; j++)
		{
			if (i < 1 || j < 1 || i > map->mx || j > map->my)
				continue;
			if (i == x && j == y)
				continue;
			if (map->stage[i][j] == FLAGED)
				cnt++;
		}
	}
	return cnt;
}

int fnOptLeftClick(int x, int y, map *m)
{
	if (!m->generated)
		Setmine(m, x, y, (unsigned int)time(NULL));
	/**
	 * @brief 地图当前状态
	 *
	 */
	int map_stage;

	map_stage = m->stage[x][y];
	/**
	 * @brief 判断当前格子是否是雷
	 *
	 */
	bool map_mine;
	map_mine = (m->mineMap[x][y] == 1) ? true : false; // ?
	/**
	 * @brief 左键实现
	 * 如果当前格子被标记或者已经打开
	 * 返回UNALLOWED
	 */
	if (map_stage == FLAGED || map_stage == COVERED || map_stage == MARKED)
		return UNALLOWED;

	if (map_mine == true)
	{
		m->stage[x][y] = COVERED;
		return BOOM;
	}

	m->stage[x][y] = COVERED;
	if (opt_count(m, x, y) == 0)
		return fnOptAuto(x, y, m);
	return ALLOWED;
}

int fnOptRightClick(int x, int y, map *m)
{

	/**
	 * @brief 地图当前状态
	 *
	 */
	int map_stage;

	map_stage = m->stage[x][y];
	switch (map_stage)
	{
	case COVERED:
		return UNALLOWED;
		break;
	case UNCOVERED:
		m->stage[x][y] = FLAGED;
		break;
	case FLAGED:
		m->stage[x][y] = MARKED;
		break;
	case MARKED:
		m->stage[x][y] = UNCOVERED;
		break;
	default:
		return ALLOWED;
		break;
	}
	return ALLOWED;
}

int fnOptMidClick(int x, int y, map *m)
{
	/**
	 * @brief 地图当前状态
	 *
	 */
	int map_stage;
	map_stage = m->stage[x][y];
	if (map_stage != COVERED)
		return UNALLOWED;
	if (opt_count(m, x, y) != opt_flag_count(m, x, y))
		return UNALLOWED;
	return fnOptAuto(x, y, m);
}

int fnOptAuto(int x, int y, map *m)
{
	#if OPT_DEBUG
	printf("\nAuto\n");
	#endif
	int flag = 0;
	if (m->autobook[x][y] == 1)
		return ALLOWED;

	m->autobook[x][y] = 1;
	for (int i = -1; i <= 1; i++)
	{
		for (int j = -1; j <= 1; j++)
		{
			int fx = x + i, fy = y + j;
			if (i == 0 && j == 0)
				continue;
			if (fx < 1 || fx > m->mx || fy < 1 || fy > m->my)
				continue;
			if (m->stage[fx][fy] == UNCOVERED)
			{
				m->stage[fx][fy] = COVERED;
				if (opt_count(m, fx, fy) == 0)
					if (fnOptAuto(fx, fy, m) == BOOM)
						flag = 1;
				if (m->mineMap[fx][fy] == 1)
					flag = 1;
			}
		}
	}
	return flag ? BOOM : ALLOWED;
}

bool opt_is_scuess(map m)
{
	/**
	 * @brief 扫雷成功条件
	 * 打开所有不是雷的格子
	 *
	 */
	int coverCnt = 0;
	for (int i = 1; i <= m.mx; i++)
	{
		for (int j = 1; j <= m.my; j++)
		{
			if (m.stage[i][j] == COVERED)
				coverCnt++;
		}
	}
	if (coverCnt == (m.mx * m.my - m.cnt))
		return true;
	else
		return false;
}

int fnTotalFlag(map *m)
{
	int flagCnt = 0;
	for (int i = 1; i <= m->mx; i++)
		for (int j = 1; j <= m->my; j++)
			if (m->stage[i][j] == FLAGED)
				flagCnt++;
	if (flagCnt != m->cnt)
		return UNALLOWED;

	for (int i = 1; i <= m->mx; i++)
	{
		for (int j = 1; j <= m->my; j++)
		{
			if (m->stage[i][j] != UNCOVERED)
				continue;
			m->stage[i][j] = COVERED;
			if (m->mineMap[i][j] == 1)
				return BOOM;
		}
	}
	return ALLOWED;
}